Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jan 27, 2026

Summary

Add a DangerJS check that validates the presence of the required legal boilerplate in PR descriptions from external contributors.

When a repository's PR template contains a "Legal Boilerplate" section, the check:

  1. Detects whether the PR author is an external contributor (via author_association)
  2. Extracts the expected boilerplate text from the repo's PR template
  3. Compares it against the PR body (whitespace-normalized)
  4. Reports a failure with a helpful markdown hint if the boilerplate is missing or modified

The check is automatically opt-in: repositories without a "Legal Boilerplate" section in their PR template are unaffected.

Known limitation: author_association reliability

The check uses the GitHub API's author_association field to distinguish internal vs. external contributors. This field is known to be unreliable when an org member has their organization membership visibility set to "Private" (which is the default). In that case, author_association may return NONE or CONTRIBUTOR instead of MEMBER, causing false positives for internal contributors.

A more reliable alternative would be to query the org membership API directly (GET /orgs/{org}/members/{username}), but that requires read:org scope and an extra API call per run. The current approach is a pragmatic starting point — if false positives become a problem, we can switch to the API-based check.

See: community discussion #18690, actions/github-script #643

Changes

  • dangerfile-utils.js: Add extractLegalBoilerplateSection, normalizeWhitespace, findPRTemplate, formatBoilerplateHint, and checkLegalBoilerplate
  • dangerfile.js: Wire checkLegalBoilerplate into checkAll()
  • dangerfile-utils.test.js: Add comprehensive tests (~40 cases) covering section extraction, whitespace normalization, hint formatting, and the full orchestration flow
  • README.md: Document the new check
  • CONTRIBUTING.md: Add test runner instructions

Validation against all getsentry repos

Scanned all 300 public, non-archived getsentry repos to verify the check works correctly:

  • 39 repos have a PR template
  • 7 of those contain a "Legal Boilerplate" section — the check activates for these
  • 32 have a PR template without the section — correctly skipped
  • 261 have no PR template at all — correctly skipped

Repos where the check activates

Repo Template path Header Extraction works?
sentry .github/PULL_REQUEST_TEMPLATE.md ### Legal Boilerplate
relay .github/PULL_REQUEST_TEMPLATE.md ### Legal Boilerplate
snuba .github/PULL_REQUEST_TEMPLATE.md ### Legal Boilerplate
sentry-cli .github/pull_request_template.md ### Legal Boilerplate
self-hosted .github/PULL_REQUEST_TEMPLATE.md ### Legal Boilerplate
vroom .github/PULL_REQUEST_TEMPLATE.md ### Legal Boilerplate
sentry-docs .github/PULL_REQUEST_TEMPLATE.md ## LEGAL BOILERPLATE

All 7 repos use the same underlying legal text. sentry-docs uses ## LEGAL BOILERPLATE (uppercase, h2) and includes an HTML comment before the text — the case-insensitive regex and whitespace normalization handle this correctly.

Template path coverage

All discovered templates use one of the 3 paths that findPRTemplate checks:

  • .github/PULL_REQUEST_TEMPLATE.md — 17 repos
  • .github/pull_request_template.md — 21 repos
  • .github/PULL_REQUEST_TEMPLATE/pull_request_template.md — 1 repo

No repos use root-level template paths, but they remain supported per GitHub's documentation.

Fixes #144

Copilot AI changed the title [WIP] Optionally verify presence of required legal notices in PR descriptions Add legal boilerplate validation for external contributors Jan 27, 2026
Copilot AI requested a review from vaind January 27, 2026 13:55
@vaind
Copy link
Contributor

vaind commented Jan 27, 2026

@copilot as usual, this needs tests...

This comment was marked as resolved.

@github-actions
Copy link
Contributor

github-actions bot commented Jan 27, 2026

Warnings
⚠️ Could not load custom Dangerfile: .github/test-dangerfile-curl.js Error: ENOENT: no such file or directory, lstat '/github/workspace/.github/test-dangerfile-curl.js'
Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Generated by 🚫 dangerJS against 8ffb2c9

vaind

This comment was marked as resolved.

- Fix fileContents bug: check for non-empty string instead of catching exceptions
- Use author_association field instead of org membership API for reliability
- Validate boilerplate content (min 50 chars) not just header presence
- Merge tests into dangerfile-utils.test.js following existing patterns
- Remove unnecessary undefined arguments from fail() calls

All 35 tests pass (20 existing + 15 legal boilerplate tests)

Co-authored-by: vaind <[email protected]>

This comment was marked as resolved.

Copilot AI requested a review from vaind January 29, 2026 08:28
Copy link
Contributor

@vaind vaind left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot fix the issue bellow and try to simplify the code, seems excesive

…ry length

Replace arbitrary 50-character check with actual content comparison.
Now validates that the exact legal boilerplate from the template is present
in the PR description by normalizing whitespace and comparing content.

Simplified logic removes unnecessary complexity and ensures the actual
legal text stays intact, not just that something exists.

Co-authored-by: vaind <[email protected]>

This comment was marked as resolved.

Copilot AI requested a review from vaind January 29, 2026 08:40
vaind and others added 3 commits January 29, 2026 11:28
Extract checkLegalBoilerplate() from dangerfile.js into dangerfile-utils.js
with dependency injection (accepts { danger, fail, markdown } as parameters)
so the orchestration logic can be tested without the DangerJS runtime.

Adds 19 tests covering author association filtering, template discovery,
missing/mismatched boilerplate detection, success cases, and markdown output.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Extract findPRTemplate helper and named constants (INTERNAL_ASSOCIATIONS,
PR_TEMPLATE_PATHS). Simplify extractLegalBoilerplateSection using findIndex.
Inline checkLegalBoilerplate call in checkAll, removing the wrapper function.
Derive test LEGAL_TEXT from the template constant to prevent drift.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Extract normalizeWhitespace, findPRTemplate, and formatBoilerplateHint
to module scope for reuse and top-down readability. Deduplicate markdown
hint construction across missing/mismatch error paths. Nest integration
tests and their helpers inside the top-level describe block.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
vaind and others added 4 commits January 30, 2026 09:09
The test command and Node version requirement were only documented
in CI workflow YAML, making it hard for new contributors to discover
how to run tests locally.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
These helpers were extracted in the previous refactor but lacked
direct unit tests, relying only on indirect coverage through the
integration tests.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Add debug log of the actual author_association value before the
internal/external check, making it easier to troubleshoot unexpected
association values. Also normalize comment style to /// to match the
rest of the file.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@vaind vaind marked this pull request as ready for review January 30, 2026 08:21
@vaind
Copy link
Contributor

vaind commented Jan 30, 2026

@sentry review

@vaind vaind requested a review from szokeasaurusrex January 30, 2026 09:56
Copy link
Member

@szokeasaurusrex szokeasaurusrex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! Thanks for implementing.

Have you been able to test that it works correctly?

Also, just wondering, is it possible to enable individual checks from the Dangerfile? Like, can I have only the legal boilerplate validation without the changelog validation? I am asking because I am intending to move the Sentry CLI/Sentry Rust repos over to the new Craft changelog generation, which means I will need to disable the Danger checks for the changelog (since manually written changelogs will overwrite Craft's auto-generated changelings). Will it be possible to still have this boilerplate validation?

@vaind
Copy link
Contributor

vaind commented Jan 30, 2026

Have you been able to test that it works correctly?

Not outside the PR. If you have a repo at hand you'd like to verify on, you can just point the danger workflow to this PRs latest commit.

can I have only the legal boilerplate validation without the changelog validation

Not right now but we can add options

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Optionally verify presence of required legal notices in PR descriptions

3 participants